<?php
/**
 * 数组处理函数
 * 
 * @author Elwin
 *
 */
class CArrays
{
	/**
	 * 递归合并多个数组,后面的元素覆盖前面相同的元素
	 *
	 * example:array_replace_recursive ( array &$array , array &$array1 [, array
	 * &$array2 [, array &$... ]] )
	 * php version < 5.3
	 *
	 * @param array $array
	 * @param array $array1
	 * @return array
	 */
	public static function array_replace_recursive($array, $array1)
	{
		$args = func_get_args ();
		$array = $args [0];
		if (! is_array ( $array ))
		{
			return $array;
		}
		for($i = 1; $i < count ( $args ); $i ++)
		{
			if (is_array ( $args [$i] ))
			{
				$array = self::merge ( $array, $args [$i] );
			}
		}
		return $array;
	}
	/**
	 * 递归合并两个数组
	 *
	 * @param array $array 合并的数组1
	 * @param array $array1 合并的数组2
	 * @return array
	 */
	public static function merge($array, $array1)
	{
		foreach ( $array1 as $key => $value )
		{
			if (! isset ( $array [$key] ) || (isset ( $array [$key] ) && ! is_array ( $array [$key] )))
			{
				$array [$key] = array ();
			}
			if (is_array ( $value ))
			{
				$value = self::merge ( $array [$key], $value );
			}
			$array [$key] = $value;
		}
		return $array;
	}
	
	/**
	 * 数组中的key的路径
	 *
	 * @param array $array 数组
	 * @param array $path 指定某个路径
	 * @return array $result 将不同级的key用'_'连接
	 */
	public function recursekey(array $array, array $path = array())
	{
		$result = array ();
		foreach ( $array as $key => $val )
		{
			$currentPath = array_merge ( $path, array (
					$key 
			) );
			if (is_array ( $val ))
			{
				$result = array_merge ( $result, self::recursekey ( $val, $currentPath ) );
			} else
			{
				$result [] = join ( '_', $currentPath );
			}
		}
		return $result;
	}
	/**
	 * 数组中的key的路径
	 *
	 * @param array $post 数组
	 * @return array $results 将不同级的key用'_'连接
	 */
	public function recursiveKeyIterator($post)
	{
		$ritit = new RecursiveIteratorIterator ( new RecursiveArrayIterator ( $post ) );
		$results = array ();
		foreach ( $ritit as $leafValue )
		{
			$path = array ();
			foreach ( range ( 0, $ritit->getDepth () ) as $depth )
			{
				$path [] = $ritit->getSubIterator ( $depth )->key ();
			}
			$results [] = join ( '_', $path );
		}
		return $results;
	}
	
	/**
	 * 指定数组key获取值
	 *
	 * @param array $array 数组
	 * @param string $index 取指定key
	 * @return NULL string array
	 */
	public function getArray($array, $index)
	{
		if (! is_array ( $array ))
			return null;
		if (isset ( $array [$index] ))
			return $array [$index];
		foreach ( $array as $item )
		{
			$return = self::getArray ( $item, $index );
			if (! is_null ( $return ))
			{
				return $return;
			}
		}
		return null;
	}
	
	/**
	 * 指定值获取key
	 *
	 * @param array $arr 数组
	 * @param string $value 查找的值
	 * @return NULL string array
	 */
	public function getKey($arr, $value)
	{
		if (! is_array ( $arr ))
			return null;
		foreach ( $arr as $k => $v )
		{
			$return = self::getKey ( $v, $value );
			if ($v == $value)
			{
				return $k;
			}
			if (! is_null ( $return ))
			{
				return $return;
			}
		}
	}
	
	/**
	 * 判断数组$arr1是数组$arr2的子集
	 *
	 * @param array $arr1 数组1
	 * @param array $arr2 数组2
	 * @return boolean $arr1 是数组$arr2的子集返回true $arr1=$arr2返回true 否则返回false
	 */
	public static function isSubSet($arr1, $arr2)
	{
		return count ( $arr1 ) == count ( array_intersect ( $arr1, $arr2 ) );
	}
	/**
	 * 过滤掉数组中为空的元素
	 *
	 * array_remove_empty(array(1,2,3, '', array(), 4)) => returns
	 * array(1,2,3,4)
	 *
	 * @param array $arr
	 * @return multitype:unknown multitype:
	 */
	public static function removeEmpty($arr)
	{
		$narr = array ();
		while ( list ( $key, $val ) = each ( $arr ) )
		{
			if (is_array ( $val ))
			{
				$val = self::removeEmpty ( $val );
				if (count ( $val ) != 0)
				{
					// yes :-)
					$narr [$key] = $val;
				}
			} else
			{
				if (trim ( $val ) != "")
				{
					$narr [$key] = $val;
				}
			}
		}
		unset ( $arr );
		return $narr;
	}
	/**
	 * 判断一维数组全是空元素
	 *
	 * @param array $array
	 * @return boolean
	 */
	public static function isEmpty($array)
	{
		foreach ( $array as $value )
			if (! empty ( $value ))
				return false;
		return true;
		/*
		 * $arr = array_filter($array, function ($value) { return
		 * (!empty($value) || $value === 0 || $value==='0'); }); return $arr;
		 */
		/*$array = array_filter($array, function($x) {
			$x = trim($x);
			return !empty($x);
		});
		
		print_r($array);*/
	}
	/**
	 *
	 * @param unknown_type $findArr
	 * @param unknown_type $key_arr
	 * @param unknown_type $depth
	 * @return NULL unknown Ambigous
	 */
	public static function GetArrKey($findArr, $key_arr, $depth = 0)
	{
		if (count ( $key_arr ) <= $depth || ! array_key_exists ( $key_arr [$depth], $findArr ))
			return NULL;
		else if (count ( $key_arr ) == $depth + 1)
			return $findArr [$key_arr [$depth]];
		return self::GetArrKey ( $findArr [$key_arr [$depth]], $key_arr, $depth + 1 );
	}
	function arrayKeyRelative($array, $current_key, $offset = 1)
	{
		$keys = array_keys ( $array );
		$current_key_index = array_search ( $current_key, $keys );
		if (isset ( $keys [$current_key_index + $offset] ))
		{
			return $keys [$current_key_index + $offset];
		}
		return false;
	}
	/**
	 * 在多维数组中查找指定索引的所有值
	 *
	 * @param array $array 查找的数组
	 * @param string $key 指定的索引
	 * @return array null 返回结果
	 */
	public static function searchKeyInArrays($array, $key)
	{
		if (is_object ( $array ))
			$array = ( array ) $array;
		$result = array ();
		foreach ( $array as $k => $value )
		{
			if (is_array ( $value ) || is_object ( $value ))
			{
				$r = self::searchKeyInArrays ( $value, $key );
				if (! is_null ( $r ))
					array_push ( $result, $r );
			}
		}
		if (array_key_exists ( $key, $array ))
			array_push ( $result, $array [$key] );
		if (count ( $result ) > 0)
		{
			$resultPlain = array ();
			foreach ( $result as $k => $value )
			{
				if (is_array ( $value ))
					$resultPlain = array_merge ( $resultPlain, $value );
				else
					array_push ( $resultPlain, $value );
			}
			return $resultPlain;
		}
		return null;
	}
	function array_search_recursive($needle, $haystack)
	{
		$path = array ();
		foreach ( $haystack as $id => $val )
		{
			
			if ($val === $needle)
				$path [] = $id;
			else if (is_array ( $val ))
			{
				$found = self::array_search_recursive ( $needle, $val );
				if (count ( $found ) > 0)
				{
					$path [$id] = $found;
				}
			}
		}
		return $path;
	}
	public function arrayColumn($findarr, $column)
	{
		$columns = array_map ( 'column', $findarr );
		return $columns;
	}
	function column($v, $column)
	{
		return $v [$column];
	}
	/**
	 * 多维数组按指定的列和排序方式排序
	 *
	 * $data, multidim array
	 * $keys, array(array(key=>col1, sort=>desc), array(key=>col2,
	 * type=>numeric))
	 *
	 * @param unknown_type $data
	 * @param unknown_type $keys
	 * @return unknown
	 */
	function multiSort($data, $keys)
	{
		// List As Columns
		foreach ( $data as $key => $row )
		{
			foreach ( $keys as $k )
			{
				$cols [$k ['key']] [$key] = $row [$k ['key']];
			}
		}
		// List original keys
		$idkeys = array_keys ( $data );
		// Sort Expression
		$i = 0;
		foreach ( $keys as $k )
		{
			if ($i > 0)
			{
				$sort .= ',';
			}
			$sort .= '$cols[' . $k ['key'] . ']';
			if ($k ['sort'])
			{
				$sort .= ',SORT_' . strtoupper ( $k ['sort'] );
			}
			if ($k ['type'])
			{
				$sort .= ',SORT_' . strtoupper ( $k ['type'] );
			}
			$i ++;
		}
		$sort .= ',$idkeys';
		// Sort Funct
		$sort = 'array_multisort(' . $sort . ');';
		eval ( $sort );
		// Rebuild Full Array
		foreach ( $idkeys as $idkey )
		{
			$result [$idkey] = $data [$idkey];
		}
		return $result;
	}
	
	/**
	 * 在二维数组中根据一个和多个索引进行排序
	 *
	 * @param array $array 排序的数组
	 * @param string|array $key The index(es) to sort the array on.
	 * @param int $sort_flags The optional parameter to modify the sorting
	 *        behavior. This parameter does not work when
	 *        supplying an array in the $key parameter.
	 *       
	 * @return array The sorted array.
	 */
	function msort($array, $key, $sort_flags = SORT_REGULAR)
	{
		if (is_array ( $array ) && count ( $array ) > 0)
		{
			if (! empty ( $key ))
			{
				$mapping = array ();
				foreach ( $array as $k => $v )
				{
					$sort_key = '';
					if (! is_array ( $key ))
					{
						$sort_key = $v [$key];
					} else
					{
						// @TODO This should be fixed, now it will be sorted as
						// string
						foreach ( $key as $key_key )
						{
							$sort_key .= $v [$key_key];
						}
						$sort_flags = SORT_STRING;
					}
					$mapping [$k] = $sort_key;
				}
				asort ( $mapping, $sort_flags );
				$sorted = array ();
				foreach ( $mapping as $k => $v )
				{
					$sorted [] = $array [$k];
				}
				return $sorted;
			}
		}
		return $array;
	}
	/**
	 * 在数组中指定的位置插入一个元素
	 *
	 * @param array $array
	 * @param string $value
	 * @param int $index
	 * @return array $array
	 */
	function array_insert(&$array, $value, $index)
	{
		return $array = array_merge ( array_splice ( $array, max ( 0, $index - 1 ) ), array (
				$value 
		), $array );
	}
	/**
	 * 在数组中将指定索引的元素移动到指定的位置
	 *
	 * @param array $array 数组
	 * @param int $oldIndex 指定索引的元素
	 * @param int $newIndex 移动到的位置
	 * @return $array 处理后的数组
	 */
	function moveToByIndex($array, $oldIndex, $newIndex)
	{
		array_splice ( $array, $newIndex, count ( $array ), array_merge ( array_splice ( $array, $oldIndex, 1 ), array_slice ( $array, $newIndex, count ( $array ) ) ) );
		return $array;
	}
	/**
	 * 替换数组的key
	 *
	 * @param array $input
	 * @param string $fromkey
	 * @param string $tokey example:
	 *        $array =array("a"=>1, "B"=>2, "c"=>3);
	 *        replaceKey($array, "B", "b");
	 *        print_r($array);
	 *       
	 *        Output:
	 *        Array
	 *        (
	 *        [a] => 1
	 *        [b] => 2
	 *        [c] => 3
	 *        )
	 */
	function replaceKey(&$input, $fromkey, $tokey)
	{
		$input = unserialize ( str_replace ( ':"' . $fromkey . '";', ':"' . $tokey . '";', serialize ( $input ) ) );
	}
	/**
	 * 将多给数组中的key替换成新的key返回替换后的结果
	 *
	 * @param array $array 需要替换key的数组
	 * @param array $fromkey 数组需要替换的key
	 * @param array $tokey 替换的key
	 * @return $return key被替换后的数组
	 */
	function replaceKeys(array $array, &$fromkey = array (), &$tokey = array ())
	{
		$return = array ();
		foreach ( $array as $key => $value )
		{
			$key = str_replace ( $fromkey, $tokey, $key );
			if (is_array ( $value ))
				$value = self::replaceKeys ( $value );
			$return [$key] = $value;
		}
		return $return;
	}
	
	/**
	 * 将多维数组转换成一维数组并过滤掉重复值
	 *
	 * @param array $a
	 * @param array $s
	 * @param integer $l
	 * @return unknown multitype:
	 */
	public static function array_flat($a, $s = array( ), $l = 0)
	{
		if (! is_array ( $a ))
			return $s;
		
		foreach ( $a as $k => $v )
		{
			if (! is_array ( $v ))
			{
				$s [] = $v;
				continue;
			}
			$l ++;
			$s = self::array_flat ( $v, $s, $l );
			$l --;
		}
		if ($l == 0)
			$s = array_values ( array_unique ( $s ) );
		return $s;
	}
	
	/**
	 * Inserts values before specific key.
	 *
	 * @param array $array
	 * @param sting/integer $position
	 * @param array $values
	 * @throws Exception
	 */
	public static function insert_before(array &$array, $position, array $values)
	{
		// enforce existing position
		if (!isset($array[$position]))
		{
			throw new Exception(strtr('Array position does not exist (:1)', array(':1' => $position)));
		}
	
		// offset
		$offset = -1;
	
		// loop through array
		foreach ($array as $key => $value)
		{
			// increase offset
			++$offset;
	
			// break if key has been found
			if ($key == $position)
			{
				break;
			}
		}
	
		$array = array_slice($array, 0, $offset, TRUE) + $values + array_slice($array, $offset, NULL, TRUE);
	
		return $array;
	}
	
	/**
	 * Inserts values after specific key.
	 *
	 * @param array $array
	 * @param sting/integer $position
	 * @param array $values
	 * @throws Exception
	 */
	public static function insert_after(array &$array, $position, array $values)
	{
		// enforce existing position
		if (!isset($array[$position]))
		{
			throw new Exception(strtr('Array position does not exist (:1)', array(':1' => $position)));
		}
	
		// offset
		$offset = 0;
	
		// loop through array
		foreach ($array as $key => $value)
		{
			// increase offset
			++$offset;
	
			// break if key has been found
			if ($key == $position)
			{
				break;
			}
		}
	
		$array = array_slice($array, 0, $offset, TRUE) + $values + array_slice($array, $offset, NULL, TRUE);
	
		return $array;
	}
	
	/**
	 * 将二维数组转成一维数组
	 * 
	 * @param array $twoDimensionalArray
	 * @return array $oneDimensionalArray
	 */
	public function twoToOneDimen($twoDimensionalArray)
	{
		$oneDimensionalArray = call_user_func_array ( 'array_merge', $twoDimensionalArray );
		return $oneDimensionalArray;
	}
}
?>